import type { ProgressInfo, ProgressStatus } from './types';

/**
 * 进度状态管理类
 */
export class ProgressStatusManager implements ProgressStatus {
  public currentChunkIndex: number = 0;
  public totalBytesWritten: number = 0;
  public workingChunkBytesWritten: number = 0;
  public workingChunkSize: number = 0;

  private cachedRemainingTime: number = 0; // 缓存的剩余时间
  private cachedSpeed: number = 0; // 缓存的速度值
  private lastBytesWritten: number = 0;
  private lastUpdateTime: number = Date.now();
  private readonly maxSamples: number = 10; // 最多保留10个样本
  private readonly minUpdateInterval: number = 100; // 最小更新间隔100ms
  private speedSamples: number[] = []; // 速度样本，用于平滑计算
  // 速度计算相关
  private startTime: number = Date.now();

  constructor(
    public readonly chunkCount: number,
    public readonly totalContentLength: number,
  ) {}

  /**
   * 完成当前分片
   */
  completeCurrentChunk(chunkSize: number): void {
    this.totalBytesWritten += chunkSize;
    this.resetWorkingChunk();
    this.currentChunkIndex++;
  }

  /**
   * 获取当前进度信息
   */
  getProgressInfo(): ProgressInfo {
    const totalBytesWritten =
      this.totalBytesWritten + this.workingChunkBytesWritten;
    const progressPercentage =
      this.totalContentLength > 0
        ? Math.round((totalBytesWritten * 100) / this.totalContentLength)
        : 0;

    // 计算上传速度和剩余时间
    const now = Date.now();
    const timeDiff = (now - this.lastUpdateTime) / 1000; // 转换为秒
    const bytesDiff = totalBytesWritten - this.lastBytesWritten;

    // 只有在满足最小更新间隔且有数据变化时才更新速度
    if (timeDiff >= this.minUpdateInterval / 1000 && bytesDiff > 0) {
      // 计算当前速度
      const currentSpeed = bytesDiff / timeDiff;

      // 只有当速度合理时才添加到样本中
      if (currentSpeed >= 0 && Number.isFinite(currentSpeed)) {
        // 添加到速度样本中
        this.speedSamples.push(currentSpeed);
        if (this.speedSamples.length > this.maxSamples) {
          this.speedSamples.shift();
        }

        // 计算平均速度并缓存
        if (this.speedSamples.length > 0) {
          this.cachedSpeed =
            this.speedSamples.reduce((sum, speed) => sum + speed, 0) /
            this.speedSamples.length;
        }

        // 计算剩余时间并缓存
        const remainingBytes = this.totalContentLength - totalBytesWritten;
        if (this.cachedSpeed > 0 && remainingBytes > 0) {
          this.cachedRemainingTime = remainingBytes / this.cachedSpeed;
        } else if (remainingBytes <= 0) {
          this.cachedRemainingTime = 0;
        }

        // 更新记录
        this.lastUpdateTime = now;
        this.lastBytesWritten = totalBytesWritten;
      }
    }

    // 如果没有速度样本或样本不足，返回缓存的值
    let uploadSpeed = this.cachedSpeed;
    let remainingTime = this.cachedRemainingTime;

    // 确保值的合理性
    if (!Number.isFinite(uploadSpeed) || uploadSpeed < 0) {
      uploadSpeed = 0;
    }
    if (!Number.isFinite(remainingTime) || remainingTime < 0) {
      remainingTime = 0;
    }

    return {
      totalBytesWritten,
      totalContentLength: this.totalContentLength,
      chunkCount: this.chunkCount,
      currentChunkIndex: this.currentChunkIndex,
      currentChunkBytesWritten: this.workingChunkBytesWritten,
      currentChunkContentLength: this.workingChunkSize,
      progressPercentage,
      uploadSpeed: Math.max(0, uploadSpeed), // 确保速度不为负数
      remainingTime: Math.max(0, remainingTime), // 确保剩余时间不为负数
    };
  }

  /**
   * 重置工作分片进度
   */
  resetWorkingChunk(): void {
    this.workingChunkBytesWritten = 0;
    this.workingChunkSize = 0;
  }

  /**
   * 更新工作分片进度
   */
  updateWorkingChunk(bytesWritten: number, chunkSize: number): void {
    this.workingChunkBytesWritten = bytesWritten;
    this.workingChunkSize = chunkSize;
  }
}
